package cn.lili.controller.pay.pufa;

import cn.hutool.core.lang.UUID;
import cn.lili.modules.bank.entity.dos.DockingBankVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.parser.HttpParser;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.html.HTMLParagraphElement;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.aliyun.openapiutil.Client.UTF8;

@Slf4j
@RestController
@RequestMapping("/manager/pay")
@Transactional(rollbackFor = Exception.class)
@Validated
public class PuFaPayTextController {
    //加密
    private static String contentType = "INFOSEC_SIGN/1.0";
    //解密
    private static String contentType2 = "INFOSEC_VERIFY_SIGN/1.0";
    //加密与解密接口
    private static String url = "http://47.93.60.120:4437";
    //请求报文接口
    private static String url2 = "http://47.93.60.120:6777";
    //甲方浦发银行账号
    private static String paymentAccount = "65140078801800000315";
    //甲方浦发银行用户名
    private static String paymentAccountName = "黑龙江融商易联网络信息科技有限公司";
    //甲方浦发银行开户号
    private static String beneficiaryBank = "2024218618";
    //单号
    private static String danhao = "3008711b2";


    /**
     * 浦发银行发起转账
     *
     //     * @param dockingBankVO
     * @return
     * @throws IOException
     */
//    public static int puFaWithdrawal(DockingBankVO dockingBankVO) throws IOException {
    public static void main(String[] args) throws IOException {
        DockingBankVO dockingBankVO = new DockingBankVO();
//        dockingBankVO.setPayeeBankName("浦发银行");                         //银行卡所属银行
//        dockingBankVO.setPayeeAcctNo("95010078801300000005");             //收款账号
//        dockingBankVO.setPayeeName("浦发2000040752");                      //收款用户名
//        dockingBankVO.setWithdrawalSn(String.valueOf(UUID.fastUUID()));   //电子凭证&单号
//        dockingBankVO.setAmount(BigDecimal.valueOf(1));
        dockingBankVO.setPayeeBankName("招商银行");                         //银行卡所属银行
        dockingBankVO.setPayeeAcctNo("6226094511663963");                 //收款账号
        dockingBankVO.setPayeeName("王新宇");                              //收款用户名
        dockingBankVO.setWithdrawalSn(String.valueOf(UUID.fastUUID()));   //电子凭证&单号
        dockingBankVO.setAmount(BigDecimal.valueOf(0.01));
        dockingBankVO.setBankCode("308261032064");                        //银行行号
        dockingBankVO.setAdCodeName("黑龙江省哈尔滨市南岗区文化街道文化宫支行");

        String sign = getSign(dockingBankVO);
//        if (true){
//            return;
//        }
        //加密签名
        String send = send(sign, contentType, url);
//        合成报文整体
        //完整串
        String complete = "<?xml version='1.0' encoding='GB2312'?><packet><head><transCode>8801</transCode><signFlag>1</signFlag><masterID>" + beneficiaryBank +
                "</masterID><packetID>" + dockingBankVO.getWithdrawalSn() + "</packetID><timeStamp>" + getDateTime() + "</timeStamp></head><body><signature>content</signature></body></packet>";
//        log.info("complete: {}", complete);
        //获取加密内容
        String contentSign = getContentSign(send);
//        log.info("contentSign: {}", replaceAllBlank(contentSign));
        //替换内容
        String content2 = complete.replace("content", replaceAllBlank(contentSign));
//        log.info("content2: {}", content2);
        //走银行接口进行转账
        String xmlContents = sendPost(content2, url2);

        String s = new String(xmlContents.getBytes("gbk"), "UTF-8");
//        System.err.println(s);
        log.info("8801报文返回内容: {}", xmlContents);
        String getContentReturnCode = getContentReturnCode(xmlContents);
//        log.info("getContentReturnCode: {}", getContentReturnCode);
        //0转账成功   转账成功获取转账结果状态
        if ("AAAAAAA".equals(getContentReturnCode)) {
            //合成报文信息
            String contentReturnSignature = getContentReturnSignature(xmlContents);
            String send1 = sendJiemi(contentReturnSignature, contentType2, url);
            log.info("8801报文解密内容: {}", send1);
//            System.err.println(send1);
//            a();
//            String resultSign = getResultSign(DockingBankVO dockingBankVO);
//            return 0;
        }
        //转账失败
//        return 1;
    }

    public static void a() throws IOException {
        String s = "<body>" +
                "<elecChequeNo>"+danhao+"</elecChequeNo>" +
                "<acctNo>95200078801300000003</acctNo>" +
                "<beginDate>20220811</beginDate>" +
                "<endDate>20220815</endDate>" +
                "<acceptNo></acceptNo>" +
                "<serialNo></serialNo>" +
                "<queryNumber>1</queryNumber>" +
                "<beginNumber>1</beginNumber>" +
                "<singleOrBatchFlag>0</singleOrBatchFlag>" +
                "</body>";
        log.info("8804报文发送内容: {}",s);
        String send = send(new String(s.getBytes("GBK"),"GBK"), contentType, url);
        String contentSign = getContentSign(send);

        String complete = "<?xml version='1.0' encoding='GB2312'?><packet><head><transCode>8804</transCode><signFlag>1</signFlag><masterID>" + beneficiaryBank +
                "</masterID><packetID>" + UUID.fastUUID() + "</packetID><timeStamp>" + getDateTime() + "</timeStamp></head><body><signature>content</signature></body></packet>";
        String content2 = complete.replace("content", replaceAllBlank(contentSign));
        String xmlContents = sendPost(content2, url2);
        log.info("8804报文返回内容: {}",xmlContents);
        String contentReturnCode = getContentReturnSignature(xmlContents);
        String s1 = sendJiemi(contentReturnCode, contentType2, url);
        log.info("8804解密内容: {}", s1);
//        return "";
    }

    /**
     * 加密信息
     *
     * @param dockingBankVO
     * @return
     */
//    public static String getSign(DockingBankVO dockingBankVO) {
//        //合成xml
//        String xml = "";
//        String xml1 = "<body><elecChequeNo>"+danhao+"</elecChequeNo><acctNo>付款账号</acctNo>" +
//                "<acctName>付款人账户名称</acctName>" +
//                "<payeeAcctNo>收款人账号</payeeAcctNo>" +
//                "<payeeName>收款人名称</payeeName>" +
//                "<amount>支付金额</amount>" +
//                "<sysFlag>同行/它行</sysFlag>" +
//                "<remitLocation>同城/异地</remitLocation>" +
//                "<remitPurpose>P</remitPurpose>";                       //佣金
//
////        String xml2 = "<payeeBankSelectFlag>1</payeeBankSelectFlag><payeeBankNo>收款行行号</payeeBankNo>";     //速选标志
//        String xml3 = "</body>";
//        //如果跨行需要有速选标志
////        if (("浦发银行".equals(dockingBankVO.getPayeeBankName()) ? false : true)) {
////            xml = xml1 + xml2 + xml3;
////        } else {
//        xml = xml1 + xml3;
////        }
////        log.info("xml: {}", xml);
//        String replace = xml
//                .replace("付款账号", paymentAccount)
//                .replace("付款人账户名称", paymentAccountName)
//                .replace("收款人账号", dockingBankVO.getPayeeAcctNo())
//                .replace("收款人名称", dockingBankVO.getPayeeName())
//                .replace("支付金额", String.valueOf(dockingBankVO.getAmount()))
//                .replace("同行/它行", "0")
//                .replace("同城/异地", "0");
////                .replace("收款行行号", dockingBankVO.getBankCode());
//        log.info("8801body内容: {}", replace);
//        return replace;
//    }

    public static String getSign(DockingBankVO dockingBankVO) {
        //初始化
        String replace = "";
        //判断是本行还是他行
        String sysFlag = dockingBankVO.getPayeeBankName().contains("浦发银行") ? "0" : "1";
        //判断是同城还是异地
        String remitLocation = dockingBankVO.getAdCodeName().contains("哈尔滨市") ? "0" : "1";
        //合成xml 初始化
        String body = "";
        String body1 = "<body>" +
                "<elecChequeNo>" + danhao + "</elecChequeNo>" +
                "<acctNo>付款账号</acctNo>" +
                "<acctName>付款人账户名称</acctName>" +
                "<payeeAcctNo>收款人账号</payeeAcctNo>" +
                "<payeeName>收款人名称</payeeName>" +
                "<amount>支付金额</amount>" +
                "<sysFlag>同行/它行</sysFlag>" +
                "<remitLocation>同城/异地</remitLocation>" +
                "<remitPurpose>P</remitPurpose>";
        String body3 = "</body>";
        String body2 = "<payeeBankNo>收款行行号</payeeBankNo>" +
                "<payeeBankSelectFlag>1</payeeBankSelectFlag>";     //速选标志
        if (sysFlag == "0" && remitLocation == "0") {
            //a. 同城本行 打款正常 0 0
            //b. 同城他行 打款正常 0 1
            body = body1 + body3;
            replace = body
                    .replace("付款账号", paymentAccount)
                    .replace("付款人账户名称", paymentAccountName)
                    .replace("收款人账号", dockingBankVO.getPayeeAcctNo())
                    .replace("收款人名称", dockingBankVO.getPayeeName())
                    .replace("支付金额", String.valueOf(dockingBankVO.getAmount()))
                    .replace("同行/它行", (sysFlag))
                    .replace("同城/异地", (remitLocation));
        } else {
            //c. 异地他行 打款正常 1 1 1
            //d. 异地本行 未测试   1 0 1
            body = body1 + body2 + body3;
            replace = body
                    .replace("付款账号", paymentAccount)
                    .replace("付款人账户名称", paymentAccountName)
                    .replace("收款人账号", dockingBankVO.getPayeeAcctNo())
                    .replace("收款人名称", dockingBankVO.getPayeeName())
                    .replace("支付金额", String.valueOf(dockingBankVO.getAmount()))
                    .replace("同行/它行", (sysFlag))
                    .replace("同城/异地", (remitLocation))
                    .replace("收款行行号", dockingBankVO.getBankCode());
        }
        log.info("replace: {}", replace);
        return replace;
    }


    /**
     * 进行加密
     *
     * @param content
     * @param contentType
     * @param url
     * @return
     * @throws IOException
     */
    public static String send(String content, String contentType, String url) throws IOException {
        //转换content内容
        byte[] bytes = StringToByte(content);
        URL urll = new URL(url);
        HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
        con1.setDoInput(true);
        con1.setDoOutput(true);
        con1.setRequestMethod("POST");
        con1.setRequestProperty("Content-Type", contentType);
        con1.connect();
        con1.getOutputStream().write(bytes);
        con1.getOutputStream().flush();
        InputStream in = con1.getInputStream();
        byte[] respBytes = toByteArray(in);
        String result = new String(respBytes);
        return result;
    }

    /**
     * 进行解密
     *
     * @param content
     * @param contentType
     * @param url
     * @return
     * @throws IOException
     */
    public static String sendJiemi(String content, String contentType, String url) throws IOException {
        //转换content内容
        byte[] bytes = StringToByte(content);
        URL urll = new URL(url);
        HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
        con1.setDoInput(true);
        con1.setDoOutput(true);
        con1.setRequestMethod("POST");
        con1.setRequestProperty("Content-Length", String.valueOf(content.length()));
        con1.setRequestProperty("Content-Type", contentType);
        con1.connect();
        con1.getOutputStream().write(bytes);
        con1.getOutputStream().flush();
        InputStream in = con1.getInputStream();
        byte[] respBytes = toByteArray(in);
        String result = new String(respBytes);
        return result;
    }

    private static byte[] toByteArray(InputStream is) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        try {
            byte[] b = new byte[4096];
            boolean var3 = false;

            int n;
            while ((n = is.read(b)) != -1) {
                output.write(b, 0, n);
            }

            byte[] var4 = output.toByteArray();
            return var4;
        } finally {
            output.close();
        }
    }

    /**
     * 发送报文
     *
     * @param content
     * @param url
     * @return
     * @throws IOException
     */
    public static String sendPost(String content, String url) throws IOException {
        String xmlContent = "00" + (content.length() + 6) + content;
        byte[] bytes = StringToByte(xmlContent);
        URL urll = new URL(url);
        HttpURLConnection con1 = (HttpURLConnection) urll.openConnection();
        con1.setDoInput(true);
        con1.setDoOutput(true);
        con1.setRequestMethod("POST");
        con1.setRequestProperty("Content-Length", "00" + (content.length() + 6));
        con1.connect();
        con1.getOutputStream().write(bytes);
        con1.getOutputStream().flush();
        InputStream in = con1.getInputStream();
        byte[] respBytes = toByteArray(in);
        String result = new String(respBytes,"gb2312");
        return result;
    }


    /**
     * String转byte
     *
     * @param content
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] StringToByte(String content) throws UnsupportedEncodingException {
        byte[] gbks = new String(content.getBytes("GBK"), "GBK").getBytes("GBK");
//        byte[] gbks = content.getBytes("gbk");
        return gbks;
    }

    /**
     * 获取send内容
     * sign
     *
     * @param aa
     * @return
     */
    public static String getContentSign(String aa) {
        String str = aa.substring(0, aa.indexOf("<sign>"));
        String bb = aa.substring(str.length() + 6, aa.length());
        String str1 = bb.substring(0, bb.indexOf("</sign>"));
        return str1;
    }

    /**
     * 获取send内容
     * returnCode
     *
     * @param aa
     * @return
     */
    public static String getContentReturnCode(String aa) {
        String str = aa.substring(0, aa.indexOf("<returnCode>"));
        String bb = aa.substring(str.length() + 12, aa.length());
        String str1 = bb.substring(0, bb.indexOf("</returnCode>"));
        return str1;
    }

    /**
     * 获取send内容
     * returnCode
     *
     * @param aa
     * @return
     */
    public static String getContentReturnSignature(String aa) {
        String str = aa.substring(0, aa.indexOf("<signature>"));
        String bb = aa.substring(str.length() + 11, aa.length());
        String str1 = bb.substring(0, bb.indexOf("</signature>"));
        return str1;
    }

    /**
     * 获取年月日时分秒
     *
     * @return
     */
    public static String getDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }

    /**
     * 去掉String换行符
     *
     * @param str
     * @return
     */
    public static String replaceAllBlank(String str) {
        String s = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\*|\t|\r|\n");
            /**
             * \n 回车(\u000a)
             * \t 水平制表符(\u0009)
             * \s 空格(\u0008)  去掉了  "\\s*|\t|r|\n"
             * \r 换行(\u000d)
             */
            Matcher m = p.matcher(str);
            s = m.replaceAll("");
        }
        return s;
    }



}
